package externaldata.passageTrainTheorique;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;


public class PassageTrainTheoriqueHandler extends DefaultHandler {
	
	private List<PassageTrainTheorique> listePTT = new ArrayList<PassageTrainTheorique>();
	private PassageTrainTheorique currentPTT = null;
	
	
	// Récupéré au début du xml (partie params)
	private String gareDua = null;
	private String date = null;
	
	// Récupéré pour chaque journey, et dans chaque stop
	private String jourArrivee = null;
	private String heureArrivee = null;
	private String minuteArrivee = null;
	// Indique si on a enfin l'heure et la minute correspondant à la gare qu'on cherche (gareDua)
	private boolean correctTime = false;
	
	private String currentStringValue = null;
	
	
	// Détection d'ouverture de balise
	@Override
	public void startElement(String namespaceUri, String localName, String rawName, Attributes attributes) throws SAXException {
		
		if (rawName.equals("VehicleJourney")) {
			
			String numTrain = attributes.getValue("VehicleJourneyExternalCode");
			
			if (numTrain != null && numTrain.matches("^DUASN[\\d]{6}.*$")) {
				currentPTT = new PassageTrainTheorique();
				currentPTT.setNumeroTrain(numTrain.substring(5, 11));
				currentPTT.setNomTrain(attributes.getValue("VehicleJourneyName"));
			}
		}
		else if (rawName.equals("Line") && currentPTT != null) {
			
			String lineCode = attributes.getValue("LineCode");
			
			if (lineCode != null && lineCode.length() == 1)
				currentPTT.setReseauTrain(lineCode.charAt(0));
		}
		else if (rawName.equals("StopPoint")) {
			
			String stopPointExternalCode = attributes.getValue("StopPointExternalCode");
			
			if (stopPointExternalCode != null && stopPointExternalCode.equals(gareDua))
				correctTime = true;
		}
	}
	
	
	// Détection de fermeture de balise 
	@Override
	public void endElement(String namespaceUri, String localName, String rawName) throws SAXException {
		
		if (rawName.equals("stopareaexternalcode")) {
			gareDua = currentStringValue;
		}
		else if (rawName.equals("date")) {
			date = currentStringValue;
		}
		else if (rawName.equals("Day") && !correctTime) {
			jourArrivee = currentStringValue;
		}
		else if (rawName.equals("Hour") && !correctTime) {
			heureArrivee = currentStringValue;
		}
		else if (rawName.equals("Minute") && !correctTime) {
			minuteArrivee = currentStringValue;
		}
		else if (rawName.equals("VehicleJourney")) {
			
			if (currentPTT != null) {
				currentPTT.setArriveeTheorique(convertToDate(date, jourArrivee, heureArrivee, minuteArrivee));
				currentPTT.setGareDua(gareDua);
				
				if (currentPTT.getArriveeTheorique() != null)				
					listePTT.add(currentPTT);
			}
			
			// On reset le currentPTT en fin de balise
			currentPTT = null;
			// Et on reset à false le correctTime pour la prochaine recherche
			correctTime = false;
		}
	}
	
	
	// Détection de caractères
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		currentStringValue = new String(ch, start, length);
	}
	
	
	// Méthode de récupération du résultat parsé
	public List<PassageTrainTheorique> getResultat() {
		return listePTT;
	}
	
	// Converti les dates et heures en format string, vers le format Date
	private Date convertToDate(String date, String jour, String heure, String minute) {
		// date est au format "yyyy|MM|dd"
		
		Date newDate = null;
		
		try {
			newDate = new SimpleDateFormat("yyyy|MM|dd HH|mm").parse(date + " " + heure + "|" + minute);
			
			int jourInt = Integer.parseInt(jour);
			
			if (jourInt > 0) {
				Calendar cal = new GregorianCalendar();
		        cal.setTime(newDate);
		        cal.add(Calendar.DATE, Integer.parseInt(jour));
		        
		        newDate = cal.getTime();
			}
			
			/*
			// Hack pour supprimer de notre parsing les trains qui passent le jour même, avant 3h00 du matin
			// qui peuvent poser problème : demander à l'auteur pour plus de précisions
			if (Integer.parseInt(jour) == 0 && Integer.parseInt(heure) < 3) {
				newDate = null;
			}
			*/
	        
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
		return newDate;
	}
}
